home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr10 / gsar106.zip / ARG_FUNC.C next >
C/C++ Source or Header  |  1993-06-01  |  9KB  |  244 lines

  1. /* arg_func.c ************************************** updated: 930328.12:48 TT
  2.  *
  3.  * Import      : #includes 
  4.  * Export      : global functions
  5.  * Description : functions for parsing the command line and getting
  6.  *               arguments from the environment
  7.  * Author      : Tormod Tjaberg
  8.  *
  9.  * Note: 
  10.  * Not all programs may want both GetOpt and GetEnvArgs. Therefore I have
  11.  * included special ifdef's for easy inclusion/exclusion.
  12.  * 
  13.  * define NO_GETOPT      ; if you don't want GetOpt
  14.  * define NO_GETENVARG   ; if you don't want GetEnvArgs
  15.  *
  16.  * The default is both functions
  17.  *
  18.  * Copyright (C) 1992-93 Tormod Tjaberg
  19.  * This is free software, distributed under the terms of the
  20.  * GNU General Public License. For details see the file COPYING
  21.  */
  22.  
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <ctype.h>
  26. #include <string.h>
  27. #include "arg_func.h"
  28.  
  29. /* gsar does not parse the environment 
  30.  */
  31. #define NO_GETENVARG
  32.  
  33. #ifndef NO_GETOPT
  34.  
  35. /* variables used by GetOpt
  36.  */
  37. int   OptInx = 1;             /* index into argv, skip argv[0]; filename */
  38. int   CurOpt;                 /* current option checked for validity */
  39. char  *pOptArg;               /* argument associated with option */
  40.  
  41.  
  42. /* GetOpt()
  43.  *
  44.  * Input  : argc - number of arguments on the command line
  45.  *          argv - pointer to the argument vector
  46.  *          pOptStr - pointer to a string containing valid option characters
  47.  * Returns: Current option being processed or an error
  48.  *
  49.  * Scan elements of argv ( length is argc ) for option characters given in
  50.  * 'pOptStr'. Each time GetOpt is called it returns the next option character
  51.  * from the option elements. When there are no more option charactes left
  52.  * GetOpt returns EOF.
  53.  *
  54.  * 'pOptStr' is a string containing all valid option characters. If an option
  55.  * character is encountered that is not in 'pOptStr', GetOpt returns:
  56.  * BAD_CHAR. The offending character is stored in 'CurOpt'.
  57.  *
  58.  * If a character in the option string is followed by a colon, it means
  59.  * that this option requires an argument. The argument can be the remainding
  60.  * text in the current argv element, or the next argv element. The argument
  61.  * is returned in 'pOptArg'. If no argument was found GetOpt returns:
  62.  * MISSING_ARG and 'pOptArg' is set to NULL. 'CurOpt' contains the offending
  63.  * option char.
  64.  *
  65.  * If a character is followed by two colons it means that this option
  66.  * wants an optional argument. If there is any text left in the current argv
  67.  * element it is returned in 'pOptarg'. If no argument was found 'pOptArg'
  68.  * is set to NULL and the option character is returned.
  69.  *
  70.  * If the option string contains '|' EOF will not be returned when a
  71.  * non option if found. Instead GetOpt returns '|'. If '|' is not specified
  72.  * NON_OPT is returned. In both cases 'pGetOpt' will poin to the non option.
  73.  * and 'OptInx' is the index of argv that contains the non option.
  74.  *
  75.  * Note, the following command line arguments have a special meaning:
  76.  *
  77.  * '-' : GetOpt returns: MISSING_OPT, 'pOptArg' is set to NULL
  78.  * '--': Forces an end of option scanning. GetOpt returns: EOF
  79.  *       Can be detected by checking if `OptInx' != argc, argv[OptInx]
  80.  *       points to the argv element following the '--'
  81.  *
  82.  * Heavily inspired by the UN?X getopt, but a bit simpler
  83.  */
  84. int GetOpt( int argc, char **argv, char *pOptStr )
  85. {
  86.    static char *pCurOpt = "";  /* pointer to current option */
  87.    char        *pOptChar;      /* pointer to char in option string */
  88.  
  89.    if ( *pCurOpt == '\0' )     /* get a new pointer */
  90.    {
  91.       if ( OptInx >= argc  )   /* no more of arguments on command line */
  92.          return EOF;
  93.  
  94.       pCurOpt = argv[OptInx];
  95.  
  96.       if ( *(pCurOpt++) != '-' )
  97.       {
  98.          pCurOpt = "";         /* next time, get a new argv */
  99.          pOptArg = argv[OptInx];
  100.          OptInx++;
  101.  
  102.          if ( strchr( pOptStr, '|' ) != NULL )
  103.             return '|';        /* This might be a filename */
  104.          else
  105.             return NON_OPT;
  106.       }
  107.  
  108.       if ( *pCurOpt == '\0')
  109.          return MISSING_OPT;
  110.  
  111.       if ( *pCurOpt == '-' )   /* catch the '--' */
  112.       {
  113.          OptInx++;             /* point to the argument behind '--' */
  114.          return EOF;
  115.       }
  116.    }
  117.  
  118.    CurOpt = *pCurOpt++;        /* CurOpt is the option character */
  119.  
  120.    if ( (pOptChar = strchr( pOptStr, CurOpt )) == NULL )
  121.       return BAD_CHAR;         /* char not in option string, culprit in CurOpt */
  122.  
  123.    if ( *(++pOptChar) != ':' ) /* option doesn't need argument */
  124.    {
  125.       pOptArg = NULL;
  126.       if ( *pCurOpt == '\0' )
  127.          ++OptInx;
  128.    }
  129.    else
  130.    {                           /* option needs an argument, but how bad ? */
  131.       if ( *pCurOpt != '\0')   /* remainder of argv is argument -d123 -> arg = 123 */
  132.          pOptArg = pCurOpt;
  133.       else
  134.          if ( *(++pOptChar) == ':' ) /* '::' optional arg, but no argument */
  135.             pOptArg = NULL;
  136.          else                        /* nothing behind option check next arg */
  137.          {
  138.             if ( argc <= ++OptInx )
  139.             {
  140.                pOptArg = NULL;       /* no arguments left but we needed one */
  141.                return MISSING_ARG;   /* return missing arg for option, culprit in CurOpt */
  142.             }
  143.             else                     /* white space separating arguments */
  144.                pOptArg = argv[ OptInx ];
  145.          }
  146.  
  147.       pCurOpt = "";                  /* next time get a new argv */
  148.       ++OptInx;                      /* next argv */
  149.    }
  150.    return CurOpt;                    /* return option letter */
  151. }
  152.  
  153. #endif
  154.  
  155. #ifndef NO_GETENVARG
  156. /* GetEnvArgs()
  157.  *
  158.  * Input  : argc - number of arguments on the command line
  159.  *          argv - pointer to the argument vector
  160.  *          pEnvVar - environment variable we are to find
  161.  * Returns: Number of arguments found in environment
  162.  *
  163.  * Create a new arvector with the enviroment arguments before the
  164.  * program arguments. This way a command line option will override
  165.  * the environment option. Any number of args can be given since we
  166.  * malloc the new argument vector. The environment variable is not destroyed.
  167.  *
  168.  * This code originally used realloc, and did not make a copy of the
  169.  * environment variable.
  170.  */
  171. int GetEnvArgs( int *argc, char ***argv, char *pEnvVar)
  172. {
  173.    char  *pEnvStr;      /* pointer to environment string */
  174.    char  **pArgV;       /* pointer to our new argument vector */
  175.    char  **pStartArgV;  /* pointer to our new argument vector */
  176.    char  *cp;           /* character pointer */
  177.    char  *pBuf;         /* pointer to copy of environment string */
  178.    int count = 0;
  179.    int envcount = 0;
  180.    unsigned char ch;
  181.  
  182.    /* fetch contents of environment variable, if any */
  183.    pEnvStr = getenv( pEnvVar );
  184.  
  185.    if ( pEnvStr == NULL || *pEnvStr == 0 )
  186.       return 0 ;
  187.  
  188.    while ( isspace( *pEnvStr ) ) /* avoid adding whitespace onto pArgV */
  189.       pEnvStr++;
  190.  
  191.    if ( (pBuf = (char *) malloc( 1 + strlen(pEnvStr) )) == NULL )
  192.       Abort( "error: unable to malloc memory for copy of environment string" );
  193.  
  194.    strcpy( pBuf,pEnvStr );     /* copy the original string into buffer */
  195.  
  196.    /* count how many arguments there are... so we can malloc */
  197.    cp = pBuf;
  198.    while( *cp != '\0' )        /* traverse environment string  */
  199.    {
  200.       while ( !isspace(*cp) && *cp != '\0' )
  201.          cp++;
  202.       while ( isspace(*cp) )
  203.          cp++;
  204.       count++;
  205.    }
  206.  
  207.    if ( count == 0 )           /* if environment string is empty */
  208.       return 0;
  209.  
  210.    envcount = count;
  211.  
  212.    /* malloc a vector that will hold all args + 1 to hold NULL */
  213.    if ( (pArgV = pStartArgV = (char **) malloc(( count + *argc + 1) * sizeof(char *))) == NULL )
  214.       Abort( "error: unable to malloc for arguments" );
  215.  
  216.    *(pArgV++) = *((*argv)++);  /* copy argv[0] ( filename ) from argv */
  217.  
  218.    do
  219.    {
  220.       *(pArgV++) = pBuf;       /* assign argument to new arg vector */
  221.       while ( (ch = *pBuf) != '\0' && !isspace(ch) )
  222.          pBuf++;               /* step over the argument */
  223.       if ( ch != '\0' )
  224.          *(pBuf++) = '\0';     /* create a null terminated string */
  225.       while ( (ch = *pBuf) != '\0' && isspace(ch) )
  226.          pBuf++;               /* step over the whitespace */
  227.    }  while (ch != '\0');
  228.  
  229.    /* now save old argc and copy in the old args */
  230.    count += *argc;
  231.  
  232.    /* copy original arg vector */
  233.    while ( --(*argc) )
  234.       *(pArgV++) = *((*argv)++);
  235.  
  236.    *pArgV = NULL;      /* The C-standard specifies that argv[argc] == NULL */
  237.    *argc = count;
  238.    *argv = pStartArgV; /* make argv point to our new vector */
  239.  
  240.    return  envcount;   /* number of args found in environment */
  241. }
  242. #endif
  243.  
  244.